use sdl2::keyboard::{Scancode, KeyboardState};

use crate::ai::ai_player::AIPlayerAdditionalInfo;
use super::player_operation::PlayerOperation;
use super::player_input::{PlayerInput, Movement};

use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Config {
    pub players: Vec<PlayerConfig>,
}

#[derive(Debug, Deserialize)]
pub struct PlayerConfig {
    left: String,
    up: String,
    right: String,
    down: String,
    fire: String,
}
#[derive(Debug)]
pub struct KeyAssignment {
    left: Scancode,
    up: Scancode,
    right: Scancode,
    down: Scancode,
    fire: Scancode,
}

// 添加从PlayerConfig到KeyAssignment的转换逻辑
impl From<PlayerConfig> for KeyAssignment {
    fn from(config: PlayerConfig) -> Self {
        //println!("fire: {:?}", config.fire);
        KeyAssignment {
            left: Scancode::from_name(&config.left).unwrap(), // 注意这里使用SCANCODE_UNKNOWN或合适的默认值
            up: Scancode::from_name(&config.up).unwrap(),
            right: Scancode::from_name(&config.right).unwrap(),
            down: Scancode::from_name(&config.down).unwrap(),
            fire: Scancode::from_name(&config.fire).unwrap(),
        }
    }
}

//设置按键
pub static mut KEY_ASSIGNMENTS: [KeyAssignment; 2] = [
    KeyAssignment { left: Scancode::A, up: Scancode::W, right: Scancode::D, down: Scancode::S, fire: Scancode::Num1 },
    KeyAssignment { left: Scancode::Left, up: Scancode::Up, right: Scancode::Right, down: Scancode::Down, fire: Scancode::Slash },
];

// 修改按键分配的函数
pub fn update_key_assignment(v: Vec<KeyAssignment>) {
    assert_eq!(v.len(), 2, "The provided vector must contain exactly two KeyAssignments.");

    // 转换Vec<KeyAssignment>为[KeyAssignment; 2]，这里直接使用unsafe转换，因为在Rust中没有直接安全转换的方法。
    // 这里假设你完全理解风险，并且此操作在你的程序上下文中是安全的。
    let array_ref: &[KeyAssignment] = v.as_slice();
    let array_ptr = array_ref.as_ptr();
    let result = unsafe { std::ptr::read(array_ptr as *const [KeyAssignment; 2]) };
    unsafe{
        KEY_ASSIGNMENTS = result;
    }
}

pub struct HumanOperation {
    pub player_number: usize,
}

impl PlayerOperation for HumanOperation {
    fn get_player_input(&mut self, keyboard_state: &KeyboardState, _: Option<AIPlayerAdditionalInfo>) -> PlayerInput {
        unsafe {
            let movement = if keyboard_state.is_scancode_pressed(KEY_ASSIGNMENTS[self.player_number].left) {
                Movement::LEFT
            } else if keyboard_state.is_scancode_pressed(KEY_ASSIGNMENTS[self.player_number].up) {
                Movement::UP
            } else if keyboard_state.is_scancode_pressed(KEY_ASSIGNMENTS[self.player_number].right) {
                Movement::RIGHT
            } else if keyboard_state.is_scancode_pressed(KEY_ASSIGNMENTS[self.player_number].down) {
                Movement::DOWN
            } else {
                Movement::NONE
            };
            let fire = keyboard_state.is_scancode_pressed(KEY_ASSIGNMENTS[self.player_number].fire);
            PlayerInput { movement, fire }
        }
    }
}